package com.example.cola.application.service;

import com.example.cola.client.api.dto.*;
import com.example.cola.client.facade.UserFacade;
import com.example.cola.domain.model.*;
import com.example.cola.domain.repository.UserRepository;
import com.example.cola.domain.service.UserDomainService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户应用服务
 * 
 * @author 资深开发专家
 * @version 1.0
 */
@Service
public class UserApplicationService implements UserFacade {
    
    private final UserRepository userRepository;
    private final UserDomainService userDomainService;
    
    public UserApplicationService(UserRepository userRepository, UserDomainService userDomainService) {
        this.userRepository = userRepository;
        this.userDomainService = userDomainService;
    }
    
    @Override
    @Transactional
    public Response<UserDTO> createUser(UserCreateCmd cmd) {
        try {
            // 创建值对象
            Email email = Email.of(cmd.getEmail());
            PhoneNumber phoneNumber = cmd.getPhoneNumber() != null ? 
                PhoneNumber.of(cmd.getPhoneNumber()) : null;
            
            // 验证注册合法性
            userDomainService.validateUserRegistration(email, phoneNumber);
            
            // 创建用户聚合根
            User user = User.create(email, phoneNumber, cmd.getName(), cmd.getPassword());
            
            // 保存用户
            userRepository.save(user);
            
            // 转换为DTO返回
            UserDTO userDTO = convertToDTO(user);
            return Response.success("用户创建成功", userDTO);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Response<UserDTO> updateUser(Long userId, UserUpdateCmd cmd) {
        try {
            UserId id = UserId.of(userId);
            User user = userRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
            
            // 验证更新合法性
            PhoneNumber phoneNumber = cmd.getPhoneNumber() != null ? 
                PhoneNumber.of(cmd.getPhoneNumber()) : null;
            userDomainService.validateUserUpdate(user, cmd.getName(), phoneNumber);
            
            // 更新用户信息
            user.updateInfo(cmd.getName(), phoneNumber);
            
            // 保存用户
            userRepository.save(user);
            
            // 转换为DTO返回
            UserDTO userDTO = convertToDTO(user);
            return Response.success("用户信息更新成功", userDTO);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    public Response<String> login(UserLoginCmd cmd) {
        try {
            // 验证登录合法性
            User user = userDomainService.validateUserLogin(cmd.getLoginId(), cmd.getPassword());
            
            // 记录登录信息（这里简化处理，实际应该记录IP等信息）
            user.recordLogin("127.0.0.1");
            userRepository.save(user);
            
            // 生成登录token（这里简化处理，实际应该使用JWT等）
            String token = "token_" + user.getId().getValue() + "_" + System.currentTimeMillis();
            
            return Response.success("登录成功", token);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    public Response<UserDTO> getUserById(Long userId) {
        try {
            UserId id = UserId.of(userId);
            User user = userRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
            
            UserDTO userDTO = convertToDTO(user);
            return Response.success(userDTO);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    public Response<PageResult<UserDTO>> queryUsers(UserQuery query) {
        try {
            List<User> users = userRepository.findUsers(
                query.getPage() - 1, query.getSize(), query.getKeyword());
            long total = userRepository.countUsers(query.getKeyword());
            
            List<UserDTO> userDTOs = users.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
            
            PageResult<UserDTO> pageResult = PageResult.of(
                userDTOs, total, query.getPage(), query.getSize());
            
            return Response.success(pageResult);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Response<Void> enableUser(Long userId) {
        try {
            UserId id = UserId.of(userId);
            User user = userRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
            
            user.enable();
            userRepository.save(user);
            
            return Response.success("用户启用成功", null);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public Response<Void> disableUser(Long userId) {
        try {
            UserId id = UserId.of(userId);
            User user = userRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
            
            user.disable();
            userRepository.save(user);
            
            return Response.success("用户禁用成功", null);
            
        } catch (Exception e) {
            return Response.error(e.getMessage());
        }
    }
    
    /**
     * 将用户聚合根转换为DTO
     */
    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId().getValue());
        dto.setEmail(user.getEmail().getValue());
        dto.setPhoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber().getValue() : null);
        dto.setName(user.getName());
        dto.setStatus(user.getStatus().getDescription());
        dto.setEmailVerified(user.getEmailVerified());
        dto.setPhoneVerified(user.getPhoneVerified());
        dto.setLastLoginTime(user.getLastLoginTime());
        dto.setLastLoginIp(user.getLastLoginIp());
        dto.setCreatedTime(user.getCreatedTime());
        dto.setUpdatedTime(user.getUpdatedTime());
        return dto;
    }
}
